# Copyright (c) 2021 Presto Labs Pte. Ltd.
# Author: gekim

import requests
from coin2.exchange.product_info import ProductInfoDefault
from coin2.exchange.symbology import SymbologyInfo

import re
import datetime
import requests
from coin2.exchange.product_info import ProductInfoDefault
from coin2.exchange.symbology import SymbologyInfo


def last_friday_of_month(year, month):
  if month == 12:
    next_month = datetime.datetime(
        year=year + 1,
        month=1,
        day=1,
        hour=8)
  else:
    next_month = datetime.datetime(
        year=year,
        month=month + 1,
        day=1,
        hour=8)
  this_month_last_day = next_month - datetime.timedelta(days=1)
  day = this_month_last_day
  while True:
    if day.weekday() == 4:
      break
    day = day - datetime.timedelta(days=1)
  return day


def quarter_expiration(trading_datetime):
  quarter_month = ((trading_datetime.month // 4 + 1) % 5) * 3
  this_quater_friday = last_friday_of_month(trading_datetime.year, quarter_month)
  if trading_datetime > this_quater_friday:
    if quarter_month == 12:
      return last_friday_of_month(trading_datetime.year + 1, 3)
    else:
      return last_friday_of_month(trading_datetime.year, quarter_month + 3)
  else:
    return this_quater_friday


def next_quarter_expiration(trading_datetime):
  return quarter_expiration(quarter_expiration(trading_datetime) + datetime.timedelta(days=1))


def to_expire(alias, expire_date):
  if alias == "FFWCSX":
    return "PERPETUAL"

  if alias == "FFICSX":
    expire_dt = datetime.datetime.utcfromtimestamp(expire_date // 1000)
    now = datetime.datetime.utcnow()
    quarterly = quarter_expiration(now)
    if (quarterly.year == expire_dt.year and quarterly.month == expire_dt.month and
        quarterly.day == expire_dt.day and quarterly.hour == expire_dt.hour):
      return "QUARTER"
    next_quarterly = next_quarter_expiration(now)
    if (next_quarterly.year == expire_dt.year and next_quarterly.month == expire_dt.month and
        next_quarterly.day == expire_dt.day and next_quarterly.hour == expire_dt.hour):
      return "NEXT_QUARTER"

  raise ValueError("raw pi expireDate or type err, or new types appear", alias, expire_date)

asset_multiplier_base_list = ["10000LADYS", "1000PEPE2"]

def generate():
  mea = 'Futures.Kucoin.v1'
  me = 'Futures.Kucoin'
  default = ProductInfoDefault()
  symbol_info = SymbologyInfo()
  data = requests.get('https://api-futures.kucoin.com/api/v1/contracts/active').json()['data']

  pis = []
  for info in data:
    if info["status"] not in ["Open", "Paused"]:
      continue

    native_symbol = info['symbol']
    native_base = info['baseCurrency']
    native_quote = info['quoteCurrency']
    base = symbol_info.native_to_norm_currency(mea, native_base)
    quote = symbol_info.native_to_norm_currency(mea, native_quote)
    symbol = "%s-%s.%s" % (base, quote, to_expire(info['type'], info["expireDate"]))

    pi = dict(
        symbol=symbol,
        base=base,
        quote=quote,
        native_symbol=native_symbol,
        native_base=native_base,
        native_quote=native_quote,
        price_ticksize=float(info['tickSize']),
        qty_ticksize=float(info['lotSize']),
        is_inverse=info['isInverse'],
        contract_value=abs(float(info["multiplier"])),
    )
    
    if base in asset_multiplier_base_list:
      regex = "^[0-9]{2,}"
      result = re.search(regex, base)
      asset_multiplier = float(result.group(0))
      asset = base[len(result.group(0)):]
      pi["asset"] = asset
      pi["asset_multiplier"] = asset_multiplier

    
    pi = {**pi, **default.product_info(me, symbol)}
    pis.append(pi)

  pis = sorted(pis, key=lambda x: x['symbol'])
  return pis


if __name__ == "__main__":
  import json
  print(json.dumps(generate(), indent=2))
